/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package game;

import com.jme3.app.SimpleApplication;
import com.jme3.bullet.BulletAppState;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.light.DirectionalLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.*;
import com.jme3.scene.control.CameraControl.ControlDirection;
import com.jme3.scene.shape.Box;
import controllers.PlayerController;


/**
 *
 * @author EVERYONE
 */
public class TestSandbox extends SimpleApplication{

    /* The conversion ratio for transforming the number of pixels the mouse
     * moves into the number of degrees you (attempt to) rotate the tank/
     * turret/camera.
     */
    private final float MOUSE_TO_DEGREES = 90f;
    
    
    BulletAppState physicsState = new BulletAppState();
    Spatial tankModel;
    Node tank;
    Material defaultMaterial, tankMaterial;
    
    
    @Override
    public void simpleInitApp() {
        //tutorialHelloSimpleApplication();
        tutorialHelloNode();
        //boxWithFloor();
    }

    /**
     * The code from the first JME tutorial: Hello SimpleApplication
     */
    private void tutorialHelloSimpleApplication() {
        // Creates a cube shape at the origin.
        // First parameter: location of the middle of the Box. Changing this
        //  effects the center of rotation.
        // Second through fourth parameters: size of the Box. These determine the
        //  "radius" of the box, so the actual size of it is 2x2x2.
        Box b = new Box(Vector3f.ZERO, 1, 1, 1);
        // Make some new geometry, using the Box shape to define what the geometry will be.
        Geometry geom = new Geometry("Box", b);
        // Load in a simple material, in this case a common, unshaded one.
        Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
        // Set the material's color to Blue.
        mat.setColor("Color", ColorRGBA.Blue);
        // Set the geometry's material (so we can actually see it).
        geom.setMaterial(mat);
        // Attach the geometry to the root of the scene graph, so it actually gets drawn.
        rootNode.attachChild(geom);
    }

    private void tutorialHelloNode() {
        // Create a blue box a 1, -1, 1
        // Box(Vec, float, float float) is deprecated, do not use.
//        Box box1 = new Box(Vector3f.ZERO, 1, 1, 1);
        Box box1 = new Box(1, 1, 1);
        Geometry blue = new Geometry("Box", box1);
        Material mat1 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
        mat1.setColor("Color", ColorRGBA.Blue);
        blue.setMaterial(mat1);
        blue.move(1, -1, 1);

        // Now create a red box above it at 1, 3, 1
        Box box2 = new Box(Vector3f.ZERO, 1, 1, 1);
        Geometry red = new Geometry("Box", box2);
        Material mat2 = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
        mat2.setColor("Color", ColorRGBA.Red);
        red.setMaterial(mat2);
        red.move(1, 3, 1);

        // Make a new node that we can attach to the scene graph, and attach
        // object to which will be drawn.
        // We want to make a new node because we can manipulate groups of objects
        // attached to a node. If we try to do this to the root node, it will
        // manipulate every object in the game. Therefore we can organize what
        // objects are manipulated in what way by attaching nodes in different
        // ways.
        Node pivot = new Node("pivot");
        rootNode.attachChild(pivot);

        // Attach our boxes to our new child node.
        pivot.attachChild(blue);
        pivot.attachChild(red);
        // Rotate all objects attached to the child node by this amount.
        pivot.rotate(0.4f, 0.4f, 0.0f);
    }
    
    /**
     * A method that Simeon wrote to create a simple scene with a box and a floor.
     */
    private void boxWithFloor() {
        //Initialize physics
        stateManager.attach(physicsState);
        mouseInput.setCursorVisible(false);
        
        initBoxWithFloor();
        
        //Initialize camera
        cam.setLocation(new Vector3f(0f,1f,0f));
        cam.lookAt(tank.getWorldTranslation(), Vector3f.UNIT_Y);
    }

    /**
     * Initialization method for the "box with floor" simple scene.
     */
    private void initBoxWithFloor() {
        defaultMaterial = new Material(assetManager, 
                "Common/MatDefs/Misc/Unshaded.j3md");
        //defaultMaterial.setTexture("GroundTexture", assetManager.loadTexture(
          //      "Textures/Terrain/Rocky/RockyTexture.jpg"));
        defaultMaterial.setColor("Color", ColorRGBA.Green);
        
        tankMaterial = new Material(assetManager,
                "Common/MatDefs/Misc/.j3md");
        tankMaterial.setColor("Color", ColorRGBA.Blue);
        
        //Create floor
        Box floor = new Box(Vector3f.ZERO,20f,0.1f,20f);
        Geometry floorGeometry = new Geometry("Floor", floor);
        floorGeometry.setMaterial(tankMaterial);
        floorGeometry.setLocalTranslation(0f, -0.1f, 0f);
        RigidBodyControl floorPhysics = new RigidBodyControl(0f);
        floorGeometry.addControl(floorPhysics);
        physicsState.getPhysicsSpace().add(floorPhysics);
        this.rootNode.attachChild(floorGeometry);

        //Create tank
        tank = new Node("Tank");
        Mesh tankMesh = new Box(Vector3f.ZERO, 1f, 0.25f, 0.5f);
        tankModel = new Geometry("Tank Model", tankMesh);
        tankModel.setMaterial(tankMaterial);
        tank.setLocalTranslation(5f, 0.5f, 0f);
        
        tank.addControl(new TankControl(tank));
        PlayerController player1Input = new PlayerController(this.inputManager, 
                tank);
        tank.attachChild(tankModel);
        this.rootNode.attachChild(tank);
        
        //Camera
        this.flyCam.setEnabled(true);
        CameraNode camera = new CameraNode("Player Camera",this.cam);
        camera.setControlDir(ControlDirection.SpatialToCamera);
        camera.setLocalTranslation(5f, 0.5f, 0f);
        tank.attachChild(camera);
        
        //Add lighting
        DirectionalLight light = new DirectionalLight();
        light.setDirection(new Vector3f(1f,0.7f,1f));
        this.rootNode.addLight(light);
    }
    
    public static void main(String[] args){
        TestSandbox app = new TestSandbox();
        app.start();
    }
}
